package org.jeecg.sms.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.DySmsEnum;
import org.jeecg.common.util.DataUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.message.entity.SysMessage;
import org.jeecg.modules.message.handle.enums.SendMsgStatusEnum;
import org.jeecg.modules.message.service.ISysMessageService;
import org.jeecg.modules.message.service.ISysMessageTemplateService;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.sms.api.RemoteSmsService;
import org.jeecg.sms.api.dto.MsgRequest;
import org.jeecg.sms.api.dto.MsgResponse;
import org.jeecg.sms.config.SocProperties;
import org.jeecg.sms.constant.SmsConstant;
import org.jeecg.sms.model.SendSmsCodeModel;
import org.jeecg.sms.model.util.SmsModelUtil;
import org.jeecg.sms.service.ISmsService;
import org.jeecg.sms.util.SlpMD5;
import org.jeecg.sms.util.SmsUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 短信服务
 *
 * @author qiang.zhou
 * @createtime 2023-03-14  13:39
 */
@Slf4j
@Service
public class ISmsServiceImpl implements ISmsService {
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private ISysMessageTemplateService sysMessageTemplateService;
    @Resource
    private ISysMessageService sysMessageService;
    @Resource
    private SocProperties socProperties;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private RemoteSmsService remoteSmsService;

    @Value("${sms.appKey}")
    private String appKey;

    @Value("${sms.appSecret}")
    private String appSecret;

    @Value("${sms.testFlag:1}")
    private String testFlag;

    @Value(("#{${sms.templateMap:{}}}"))
    private Map<String,String> templateMap;

    @Override
    public Result<?> sendSmsCode(SendSmsCodeModel model) {
        String msgTemplate = null;
        String title = null;
        if (CommonConstant.SMS_TPL_TYPE_1.equals(model.getSmsMode())) {
            SysUser sysUser = sysUserService.getUserByPhone(model.getMobile());
            if(sysUser!=null) {
                return Result.error("手机号已经注册，请直接登录！");
            }
            msgTemplate = sysMessageTemplateService.getSmsTemplateByCode(DySmsEnum.REGISTER_TEMPLATE_CODE);
            title = DySmsEnum.REGISTER_TEMPLATE_CODE.getSignName();
        } else {
            //登录模式，校验用户有效性
            SysUser sysUser = sysUserService.getUserByPhone(model.getMobile());
            Result result = sysUserService.checkUserIsEffective(sysUser);
            if(!result.isSuccess()) {
                String message = result.getMessage();
                String userNotExist="该用户不存在，请注册";
                if(userNotExist.equals(message)){
                    result.error500("该用户不存在或未绑定手机号");
                }
                return result;
            }

            // smsMode 短信模板方式  0 .登录模板、1.注册模板、2.忘记密码模板
            if (CommonConstant.SMS_TPL_TYPE_0.equals(model.getSmsMode())) {
                //登录模板
                msgTemplate = sysMessageTemplateService.getSmsTemplateByCode(DySmsEnum.LOGIN_TEMPLATE_CODE);
                title = DySmsEnum.LOGIN_TEMPLATE_CODE.getSignName();
            } else if(CommonConstant.SMS_TPL_TYPE_2.equals(model.getSmsMode())) {
                // 忘记密码模板
                msgTemplate = sysMessageTemplateService.getSmsTemplateByCode(DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
                title = DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE.getSignName();
            }
        }

        if (StringUtils.isBlank(msgTemplate)) {
            log.error("未知的登录模式或短信模板未配置");
            return Result.error("未知的登录模式");
        }

        String smsCode = DataUtil.randomNum(SmsConstant.SMS_CODE_LENGTH);

        // 将code存储到redis并设置超时时间
        Boolean absentFlag = redisTemplate.opsForValue().setIfAbsent(SmsConstant.SMS_CODE_KEY + model.getMobile(), smsCode, socProperties.getSms().getSmsCodeExpire(), TimeUnit.SECONDS);
        if (Boolean.FALSE.equals(absentFlag)) {
            return Result.error("获取短信验证码太频繁，请稍后重试");
        }
        // 发送短信
        this.send(model.getMobile(), title, msgTemplate, smsCode,model.getSmsMode());
        return Result.ok(socProperties.getSms());
    }

    @Override
    public Result<?> send(String phone, String title, String msg, String smsCode, String smsMode) {
        // 处理参数
        try {
            msg = String.format(msg, smsCode);
        } catch (Exception e) {
            log.error("短信参数处理失败");
            return Result.error("短信参数不一致，请检查");
        }

        SysMessage sysMessage = SmsModelUtil.buildSysMessage(msg, phone, title,smsCode,smsMode);
        sysMessageService.save(sysMessage);

        // 发布Redis订阅
//        redisTemplate.convertAndSend(SmsConstant.SOC_MESSAGE_CHANNEL, sysMessage.getId());
        this.sendSms(sysMessage.getId());
        return Result.OK();
    }

    @Override
    public void sendSms(String messageId) {
        SysMessage message = sysMessageService.getById(messageId);
        if (null == message) {
            log.warn("未知的消息id");
            return;
        }

        log.info("查询短信的内容【{}】", JSON.toJSONString(message));
        // 发送短信
        MsgResponse respMsg = this.smsService(message);
        log.info("调用第三方短信接口返回：【{}】,code :{}",respMsg,respMsg.getRspCode());
        String esSendStatus = SmsConstant.SMS_SUCCESS_CODE.equals(respMsg.getRspCode()) ? SendMsgStatusEnum.SUCCESS.getCode() : SendMsgStatusEnum.FAIL.getCode();
        log.info("调用第三方短信状态码：【{}】",esSendStatus);
        // 更新发送状态
        sysMessageService.lambdaUpdate()
                .set(SysMessage::getEsSendTime, new Date())
                .set(SysMessage::getEsSendStatus, esSendStatus)
                .set(SysMessage::getEsResult, JSON.toJSONString(respMsg))
                .set(SysMessage::getUpdateTime, new Date())
                .eq(SysMessage::getId, message.getId())
                .update();
    }

    private String calculateBrief(String action, String xmlData) {
        StringBuffer sb = new StringBuffer();
        sb.append(socProperties.getSms().getPwd())
                .append(action)
                .append(xmlData)
                .append(socProperties.getSms().getTarget());
        return SlpMD5.generateCheckCode(sb.toString());
    }

    /**
     * 发送短信
     * @param smsMessage
     * @return
     */
    public MsgResponse smsService(SysMessage smsMessage) {
        Map<String,String> headers = new HashMap<>();
        headers.put("x-pmc-app-key",appKey);
        headers.put("x-pmc-biz-id",(SmsUtils.generateScenarioId()));
        headers.put("x-pmc-test-flag",(testFlag));
        headers.put("x-pmc-timestamp",(DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN)));
        headers.put("x-pmc-sign",(SmsUtils.getSign(headers.get("x-pmc-biz-id"),appSecret,headers.get("x-pmc-timestamp"))));

        MsgRequest req = new MsgRequest();
        req.setMobile(smsMessage.getEsReceiver());
        req.setSeqID(smsMessage.getId());
        req.setTemplateID(templateMap.get(smsMessage.getRemark()));
        req.setTemplateParams(smsMessage.getEsParam());
        MsgResponse response = new MsgResponse();
        try {
            response =  remoteSmsService.sendMsg(req,headers);
        }catch (Exception e){
            log.error("调用第三方异常，异常明细：{}",e.getMessage());
            throw e;
        }
        log.info("请求消息平台req:{},header:{},response:{}", JSON.toJSONString(req),JSON.toJSONString(headers),JSON.toJSONString(response));
        return response;
    }


}
